package com.song.flowable.controller;

import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.*;
import org.flowable.engine.*;
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.engine.runtime.ProcessInstanceBuilder;
import org.flowable.image.ProcessDiagramGenerator;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@RestController
public class LeaveController {
    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private ProcessEngine processEngine;

    @Autowired
    private TaskService taskService;

    @RequestMapping("showPic")
    public void showPic(HttpServletResponse response, String processId) throws Exception {
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult();
        if (processInstance == null){
            return;
        }
        List<Execution> executions = runtimeService.createExecutionQuery().processInstanceId(processId).list();
        List<String> activityIds = new ArrayList<>();
        List<String> flows = new ArrayList<>();
        for (Execution execution : executions){
            List<String> activeActivityIds = runtimeService.getActiveActivityIds(execution.getId());
            activityIds.addAll(activeActivityIds);
        }
        //生成流程图
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId());
        ProcessEngineConfiguration processEngineConfiguration = processEngine.getProcessEngineConfiguration();
        ProcessDiagramGenerator processDiagramGenerator = processEngineConfiguration.getProcessDiagramGenerator();
        InputStream is = processDiagramGenerator.generateDiagram(
                bpmnModel,
                "png",
                activityIds,
                flows,
                processEngineConfiguration.getActivityFontName(),
                processEngineConfiguration.getLabelFontName(),
                processEngineConfiguration.getAnnotationFontName(),
                processEngineConfiguration.getClassLoader(),
                1.0,
                false
        );
        OutputStream os = null;
        byte[] bytes = new byte[1024];
        int len = 0;
        try {
            os = response.getOutputStream();
            while ((len = is.read(bytes)) != -1){
                os.write(bytes, 0 , len);
            }
        } finally {
            if (os != null){
                os.close();
            }
            if (is != null){
                is.close();
            }
        }
    }

    /**
     * 开启一个流程
     */
    @RequestMapping("start")
    public void start(String staffId){
        Map<String, Object> map = new HashMap<>();
        map.put("leaveTask", staffId);
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("ask_for_leave", map);
        runtimeService.setVariable(processInstance.getId(), "name", "张三");
        runtimeService.setVariable(processInstance.getId(), "reason", "年假");
        runtimeService.setVariable(processInstance.getId(), "days", "5");
        log.info("创建请假流程{}成功", processInstance.getId());
//
//        ProcessInstanceBuilder processInstanceBuilder = runtimeService.createProcessInstanceBuilder();
//        processInstanceBuilder.businessKey("ask_for_leave");
//        ProcessInstance instance = processInstanceBuilder.start();

    }

    /**
     * 提交给组长
     */
    @RequestMapping("submit")
    public void submit(String staffId, String zzId){
        List<Task> tasks = taskService.createTaskQuery().taskAssignee(staffId).orderByTaskId().desc().list();
        taskService.createTaskQuery().taskAssignee(staffId).processInstanceId("").active().singleResult();
        for (Task task : tasks) {
            log.info("任务ID:{} 任务处理人:{} 任务是否挂起:{}", task.getId(), task.getAssignee(), task.isSuspended());
            Map<String, Object> map = new HashMap<>();
            map.put("zzTask", zzId);
            taskService.complete(task.getId(), map);
        }
    }

    /**
     * 组长审批
     */
    @RequestMapping("zzApprove")
    public void zzApprove(String zzId, String jlId, String checkResult){
        List<Task> tasks = taskService.createTaskQuery().taskAssignee(zzId).orderByTaskId().desc().list();
        for (Task task : tasks) {
            log.info("组长:{} 审批任务:{}", task.getAssignee(), task.getId());
            Map<String, Object> map = new HashMap<>();
            map.put("jlTask", jlId);
            map.put("checkResult", checkResult);
            taskService.complete(task.getId(), map);
        }
    }

    /**
     * 经理审批
     */
    @RequestMapping("jlApprove")
    public void jlApprove(String jlId, String checkResult){
        List<Task> tasks = taskService.createTaskQuery().taskAssignee(jlId).orderByTaskId().desc().list();
        for (Task task : tasks) {
            log.info("经理:{} 审批任务:{}", task.getAssignee(), task.getId());
            Map<String, Object> map = new HashMap<>();
            map.put("checkResult", checkResult);
            taskService.complete(task.getId(), map);
        }
    }

    /**
     * 获取节点信息
     */
    @RequestMapping("nodeInfo")
    public void nodeInfo(String taskId){
        Task result = taskService.createTaskQuery().taskId(taskId).singleResult();
        ExecutionEntity executionEntity = (ExecutionEntity) runtimeService.createExecutionQuery().executionId(result.getExecutionId()).singleResult();
        String activityId = executionEntity.getActivityId();
        BpmnModel bpmnModel = repositoryService.getBpmnModel(result.getProcessDefinitionId());
        FlowNode flowNode = (FlowNode) bpmnModel.getFlowElement(activityId);
        List<SequenceFlow> outgoingFlows = flowNode.getOutgoingFlows();
        for (SequenceFlow sequenceFlow : outgoingFlows) {
            //当前节点
            FlowElement sourceFlowElement = sequenceFlow.getSourceFlowElement();
            log.info("当前节点：id={}，name={}", sourceFlowElement.getId(), sourceFlowElement.getName());
            //下一节点
            FlowElement targetFlowElement = sequenceFlow.getTargetFlowElement();
            if (targetFlowElement instanceof UserTask){
                log.info("下一节点：id={}，name={}", targetFlowElement.getId(), targetFlowElement.getName());
            }else if (targetFlowElement instanceof EndEvent){
                log.info("下一节点为结束节点：id={}，name={}", targetFlowElement.getId(), targetFlowElement.getName());
            }
        }
    }
}
